import { Injectable } from '@angular/core'
import { HttpClient } from '@angular/common/http'
import { Observable, of, throwError } from 'rxjs'
import { catchError, map } from 'rxjs/operators'

import { COMB_URL } from 'app/utils/contraints'
import { AcquirerService } from './acquirer.service'
import {
  IAcquirerQueryParams,
  Acquirer,
  IInstitutionPagination,
  IUpdateAcquirerBaseInfo,
  IUpdateAcquirerTradeInfo,
  IUpdateAcquirerQRFeature,
  IUpdateAcquirerAudit,
  IUpdateAcquirerSettlement,
  IUpdateAcquirerCardFeature,
  QrChannel,
  ECUPIChannel,
  IUpdateAcquirerFeature,
} from '@shared/interfaces/acquirer'
import { preProcessParams, encodeParams } from '@shared/decorators'
import { IResponse } from '@shared/interfaces/response'
import { ECategoryUrl } from '@shared/interfaces/trade'

@Injectable()
export class AcquirerAlinterService implements AcquirerService {
  constructor(private http: HttpClient) {}

  @preProcessParams()
  @encodeParams()
  getList(params: IAcquirerQueryParams, str?: string): Observable<IInstitutionPagination> {
    const url = `${COMB_URL}/camel/institutions?${str}`
    return this.http.get<IInstitutionPagination>(url).pipe(
      map(resp => {
        return resp
      }),
      catchError(err => throwError(err)),
    )
  }

  getOne(insCode: string): Observable<Acquirer> {
    const url = `${COMB_URL}/camel/institution/${insCode}/full`
    return this.http
      .get<Acquirer>(url, {
        withCredentials: true,
        observe: 'response',
      })
      .pipe(
        map(response => {
          const { status, body } = response
          if (status === 200) {
            const acquirer = new Acquirer()
            Object.assign(acquirer, body)
            return acquirer
          }
          throwError(response)
        }),
        catchError(err => throwError(err)),
      )
  }

  delete(insCode: string): Observable<boolean> {
    const url = `/master/institution/delete/v1?insCode=${insCode}`
    return this.http
      .post<IResponse>(url, {
        withCredentials: true,
      })
      .pipe(
        map(res => {
          if (res.status !== 0) {
            throw new Error(res.message)
          }
          return true
        }),
        catchError(err => {
          console.log('error is ', err)
          return of(false)
        }),
      )
  }

  create(acq: Acquirer): Observable<Acquirer> {
    const url = `/comb/camel/institution`
    return this.http.post<Acquirer>(url, acq)
  }

  updateBaseInfoOfAcquirer(data: IUpdateAcquirerBaseInfo, insCode: string): Observable<Acquirer> {
    const url = `${COMB_URL}/camel/institution/${insCode}`
    return this.http.put<Acquirer>(url, data).pipe(catchError(err => throwError(err)))
  }

  updateTradeInfoOfAcquirer(data: IUpdateAcquirerTradeInfo, insCode: string): Observable<Acquirer> {
    const url = `${COMB_URL}/camel/institution/${insCode}/trade`
    return this.http.put<Acquirer>(url, data).pipe(catchError(err => throwError(err)))
  }

  updateFeaturesOfAcquirer(data: IUpdateAcquirerFeature, insCode: string): Observable<Acquirer> {
    const url = `${COMB_URL}/camel/institution/${insCode}/feature`
    return this.http.put<Acquirer>(url, data)
  }

  updateQRFeaturesOfAcquirer(data: IUpdateAcquirerQRFeature, insCode: string): Observable<Acquirer> {
    const url = `${COMB_URL}/zebra/institution/${insCode}/feature`
    return this.http.put<Acquirer>(url, data).pipe(catchError(err => throwError(err)))
  }

  updateCardFeaturesOfAcquirer(data: IUpdateAcquirerCardFeature, insCode: string): Observable<Acquirer> {
    const url = `${COMB_URL}/turtle/institution/${insCode}/feature`
    return this.http.put<Acquirer>(url, data).pipe(catchError(err => throwError(err)))
  }

  updateAuditOfAcquirer(data: IUpdateAcquirerAudit, insCode: string): Observable<Acquirer> {
    const url = `${COMB_URL}/camel/institution/${insCode}/audit`
    return this.http.put<Acquirer>(url, data).pipe(catchError(err => throwError(err)))
  }

  updateSettlementAcquirer(data: IUpdateAcquirerSettlement, insCode: string): Observable<Acquirer> {
    const url = `${COMB_URL}/camel/institution/${insCode}/settlement`
    return this.http.put<Acquirer>(url, data).pipe(catchError(err => throwError(err)))
  }

  updateChannelForAcquirer(category: ECategoryUrl, insCode: string, id: string, body: QrChannel): Observable<boolean> {
    const url = `${COMB_URL}/${category}/institution/${insCode}/channel/${id}`
    return this.http.put<boolean>(url, body).pipe(catchError(err => throwError(err)))
  }

  deleteChannelForAcquirer(category: ECategoryUrl = ECategoryUrl.qr, insCode: string, id: string): Observable<boolean> {
    const url = `${COMB_URL}/${category}/institution/${insCode}/channel/${id}`
    return this.http.delete<boolean>(url).pipe(catchError(err => throwError(err)))
  }

  createChannelForAcquirer(
    category: ECategoryUrl = ECategoryUrl.qr,
    insCode: string,
    channel: QrChannel,
  ): Observable<boolean> {
    const url = `${COMB_URL}/${category}/institution/${insCode}/channel`
    return this.http.post<boolean>(url, channel).pipe(catchError(err => throwError(err)))
  }

  /* 根据 chanCode 和 chanMerId 去拿渠道但详细信息 */
  getExistedChannel(
    chanCode: string,
    chanMerID: string,
    category: ECategoryUrl = ECategoryUrl.qr,
  ): Observable<QrChannel> {
    const url = `${COMB_URL}/${category}/channel/${chanCode}/${chanMerID}`
    return this.http.get<QrChannel>(url).pipe(catchError(err => throwError(err)))
  }

  /** 冻结 */
  freeze(insCode: string): Observable<boolean> {
    const url = `${COMB_URL}/camel/institution/${insCode}/freeze`
    return this.http.put<boolean>(url, {})
  }

  /** 解冻 */
  unfreeze(insCode: string): Observable<boolean> {
    const url = `${COMB_URL}/camel/institution/${insCode}/unfreeze`
    return this.http.put<boolean>(url, {})
  }

  updateEcChannelForAcquirer(category: ECategoryUrl, insCode: string, id: string, body: ECUPIChannel): Observable<boolean> {
    const url = `${COMB_URL}/${category}/institution/${insCode}/channel/${id}`
    return this.http.put<boolean>(url, body).pipe(catchError(err => throwError(err)))
  }

  deleteEcChannelForAcquirer(category: ECategoryUrl = ECategoryUrl.ec, insCode: string, id: string): Observable<boolean> {
    const url = `${COMB_URL}/${category}/institution/${insCode}/channel/${id}`
    return this.http.delete<boolean>(url).pipe(catchError(err => throwError(err)))
  }

  createEcChannelForAcquirer(
    category: ECategoryUrl = ECategoryUrl.ec,
    insCode: string,
    channel: ECUPIChannel,
  ): Observable<boolean> {
    const url = `${COMB_URL}/${category}/institution/${insCode}/channel`
    console.log('createEcChannelForAcquirer url:', url)
    console.log('createEcChannelForAcquirer channel:', JSON.stringify(channel))
    return this.http.post<boolean>(url, channel).pipe(catchError(err => throwError(err)))
  }
}
